package org.trc.traffic.analysis.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JFileChooser;

import org.geotools.data.DataUtilities;
import org.geotools.data.DefaultTransaction;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.shapefile.shp.ShapefileException;

import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.data.simple.SimpleFeatureStore;

import org.geotools.factory.CommonFactoryFinder;
import org.geotools.feature.FeatureCollections;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.JTS;

//import org.geotools.geometry.jts.JTSFactoryFinder;
//import com.vividsolutions.jts.geom.GeometryFactory;

import org.geotools.referencing.CRS;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.geotools.swing.data.JFileDataStoreChooser;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LineString;
import com.vividsolutions.jts.geom.MultiLineString;
import com.vividsolutions.jts.geom.Point;

import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

import org.trc.io.DBAccess;
import org.trc.io.DBUpdate;
import org.trc.network.*;
import org.trc.traffic.BasicLinkTraffic;
import org.trc.traffic.AggLinkTraffic;
import org.trc.trajectory.Trajectory;
import org.trc.trajectory.TrajectoryPoint;
import org.trc.trajectory.Trip;


public class TrafficDataAnalysis {
	private static Network road = null;
	
	public static void init(String roadShapefileURL, String roadODInfoURL) throws ShapefileException, IOException, SchemaException{
		road =  new Network(roadShapefileURL, true);
		if(roadODInfoURL != null)
			road.generateLinearNetworkByMultiLink(roadODInfoURL);
	}
	
	//获取道路中间点
	public static void getRoadSegmentCentroid(String shapeRoadNetworkURL)
			throws MalformedURLException, IOException, SchemaException {
		// read shape file and get feature colletion
		FileDataStore readDataStore = FileDataStoreFinder.getDataStore(new File(shapeRoadNetworkURL));
		SimpleFeatureCollection featureCollection = readDataStore.getFeatureSource().getFeatures();

		// write new shape file
		JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
	    chooser.setDialogTitle("Save a new shapefile");
	    
	    chooser.setSaveFile(new File(shapeRoadNetworkURL));
	    
        if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) {
            return;
        }
        
        File outputShapefile = chooser.getSelectedFile();
		
		ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		Map<String, Serializable> params = new HashMap<String, Serializable>();
		params.put("url", outputShapefile.toURI().toURL());
		params.put("create spatial index", Boolean.TRUE);
		ShapefileDataStore writeDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);

		// specify the feature type
		final SimpleFeatureType TYPE = DataUtilities.createType("SamplePoint",
				"GEOM:Point:srid=4326," + "ID:String," + "AVG:double," + "STATUS:int");

		writeDataStore.createSchema(TYPE);
		writeDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);

		//prepare new feature collection	
		SimpleFeatureCollection collection = FeatureCollections.newCollection();
		SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);

		String edgeID = null;
		Double avgSpeed = 0.0;
		Integer status = 0;
		Point geom = null;

		SimpleFeatureIterator iterator = featureCollection.features();
		SimpleFeature feature = null;
		MultiLineString line = null;
		
		while (iterator.hasNext()) {
			feature = iterator.next();
			line = (MultiLineString) feature.getDefaultGeometry();
			geom = line.getCentroid();
			edgeID = (String) feature.getAttribute("ID");
			avgSpeed = (Double) feature.getAttribute("AVG");
			status = (Integer) feature.getAttribute("STATUS");
			// create feature
			featureBuilder.add(geom);
			featureBuilder.add(edgeID);
			featureBuilder.add(avgSpeed);
			featureBuilder.add(status);
			feature = featureBuilder.buildFeature(null);
			collection.add(feature);
		}

		//create transaction
		Transaction transaction = new DefaultTransaction("create");
		String typeName = writeDataStore.getTypeNames()[0];
		SimpleFeatureSource featureSource = writeDataStore.getFeatureSource(typeName);

		if (featureSource instanceof SimpleFeatureStore) {
			SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
			featureStore.setTransaction(transaction);
			try {
				featureStore.addFeatures(collection);
				transaction.commit();
			} catch (Exception problem) {
				problem.printStackTrace();
				transaction.rollback();
			} finally {
				transaction.close();
			}
			System.exit(0); // success!
		} else {
			System.out.println(typeName + " does not support read/write access");
			System.exit(1);
		}
	}

	//获取道路节点
	public static void getRoadSegmentsEndPonit(String RoadSegmentShapefileURL) throws ShapefileException, IOException{
		//读取路网弧段,获取节点集合
		
/*      File file = JFileDataStoreChooser.showOpenFile("shp", null);
        if (file == null) {
            return;
        }*/
        
		Network road = new Network(RoadSegmentShapefileURL, false);
		Map<String, Node> nodeCollection = road.nodeCollection;
		
		//选择生成的文件
		JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
	    chooser.setDialogTitle("Save a new shapefile for muliple congestion clusters");
	    chooser.setSaveFile(new File("C:\\RoadNodes.shp"));
	    
        if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) {
            return;
        }
        
        File outputShapefile = chooser.getSelectedFile();
		
		// 定义要素类型
		SimpleFeatureType TYPE = null;
		try {
			TYPE = DataUtilities.createType(
					"Node", 
					"GEOM:Point:srid=4326," + "ID:String," + "DEGREE:int"
			);
		} catch (SchemaException e) {
			e.printStackTrace();
		}

		// 要素集容器
		SimpleFeatureCollection collection = FeatureCollections.newCollection();

		// 要素构造器
		SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
		SimpleFeature feature = null;
		String id = null;
		int degree = 0;
		Point point = null;

		// 要素构建
        for (Node node : nodeCollection.values()){
        	id = node.getID();
        	degree = node.getDegree();
        	point = node.point;  	
			featureBuilder.add(point);
			featureBuilder.add(id);
			featureBuilder.add(degree);
			feature = featureBuilder.buildFeature(null);
			collection.add(feature);
        }

		//构建输出文件的 dataStoreFactory,设定Factory的各项参数
		ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		
		Map<String, Serializable> params = new HashMap<String, Serializable>();
		params.put("url", outputShapefile.toURI().toURL());
		params.put("create spatial index", Boolean.TRUE);
		
		ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
		newDataStore.createSchema(TYPE);
		newDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84); 

		// 通过 '事务' 输出 shape文件
		Transaction transaction = new DefaultTransaction("create");
		String typeName = newDataStore.getTypeNames()[0];
		SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);

		if (featureSource instanceof SimpleFeatureStore) {
			SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
			featureStore.setTransaction(transaction);
			try {
				featureStore.addFeatures(collection);
				transaction.commit();
			} catch (Exception problem) {
				problem.printStackTrace();
				transaction.rollback();
			} finally {
				transaction.close();
			}
			System.exit(0); // success!
		} else {
			System.out.println(typeName + " does not support read/write access");
			System.exit(1);
		}
	}
	
	//生成Weka的arff格式
	public static void shape2arff(String shapefileURL, String wekafileURL)throws IOException {
		// 读取Shape文件
		FileDataStore fileDataStore = FileDataStoreFinder.getDataStore(new File(shapefileURL));
		SimpleFeatureType  schema = fileDataStore.getSchema();
		SimpleFeatureCollection featureCollection = fileDataStore.getFeatureSource().getFeatures();
				
		// 获取文本输出器
		PrintWriter textWriter = new PrintWriter(new File(wekafileURL));

		// 打印头信息
		textWriter.println("@relation spatialpoint");
		textWriter.println();
		textWriter.println("@attribute ID string");
		textWriter.println("@attribute AVG numeric");
		textWriter.println("@attribute STATUS numeric");
		textWriter.println("@attribute Long numeric");
		textWriter.println("@attribute Latt numeric");
		textWriter.println();
		textWriter.println("@data");
		textWriter.println();

		// print attribute values
		SimpleFeature feature = null;
		Point geom = null;
		
		SimpleFeatureIterator iterator = featureCollection.features();
		CoordinateReferenceSystem fromCRS = schema.getCoordinateReferenceSystem();
		while (iterator.hasNext()) {
			feature = iterator.next();
			if (!feature.getAttribute("STATUS").toString().equals("0"))
				continue;
			textWriter.print(feature.getAttribute("ID"));
			textWriter.print(", ");
			textWriter.print(feature.getAttribute("AVG"));
			textWriter.print(", ");
			textWriter.print(feature.getAttribute("STATUS"));
			textWriter.print(", ");
			try {
				geom = (Point)JTS.transform((Point)feature.getDefaultGeometry(), getTransformFromEpsgCode(fromCRS, "EPSG:32650"));
			} catch (MismatchedDimensionException e) {
				e.printStackTrace();
			} catch (TransformException e) {
				e.printStackTrace();
			} 
			textWriter.print(geom.getX());
			textWriter.print(", ");
			textWriter.print(geom.getY());
			textWriter.println();
		}
		iterator.close();
		textWriter.close();
	}
	
	//生成轨迹的shape格式
	public static void csv2shape(String csvfileURL) throws ShapefileException, MismatchedDimensionException, IOException, TransformException, SchemaException, NoSuchAuthorityCodeException, FactoryException{
		Trajectory traj = DBAccess.getTrajectoryByCSVFile(new File(csvfileURL));
		
		// write new shape file
		JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
	    chooser.setDialogTitle("Save a new shapefile for a trajectory");
	    chooser.setSaveFile(new File("D:\\trjectory.shp"));	    
        if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) {
            return;
        }
        File outputShapefile = chooser.getSelectedFile();
		
		ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		Map<String, Serializable> params = new HashMap<String, Serializable>();
		params.put("url", outputShapefile.toURI().toURL());
		params.put("create spatial index", Boolean.TRUE);
		ShapefileDataStore writeDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);

		// specify the feature type
		final SimpleFeatureType TYPE = DataUtilities.createType(
				"SamplePoint",
				"GEOM:Point:srid=32650," 
				+ "LINKID:String," 
				+ "NUM:int,"
				+ "SPEED:double,"
				+ "DIRECTION:double,"
				+ "STATUS:int,"
				+ "TRIPID:String,"
				+ "TIME:String,"
				+ "SECONDS:int");

		writeDataStore.createSchema(TYPE);
		writeDataStore.forceSchemaCRS(CRS.decode("EPSG:32650",true));

		//prepare new feature collection	
		SimpleFeatureCollection collection = FeatureCollections.newCollection();
		SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);

		Point geom = null;
		String linkID = null;
		int num = 0;
		Double speed = 0.0;
		Double direction = 0.0;
		Integer status = 0;
		String tripid = null;
		String time = null;
		Integer seconds = 0;
		
		
		SimpleFeature feature = null;
		for(TrajectoryPoint point : traj.points) {		
			geom = point.geom;
			linkID = point.linkID;
			num++;
			speed = Double.valueOf(point.speed);
			direction = Double.valueOf(point.direction);
			status = Integer.valueOf(point.status);
			tripid = point.tripID;
			time = point.getTimeString();
			seconds = Integer.valueOf(point.seconds);
			// create feature
			featureBuilder.add(geom);
			featureBuilder.add(linkID);
			featureBuilder.add(num);
			featureBuilder.add(speed);
			featureBuilder.add(direction);
			featureBuilder.add(status);
			featureBuilder.add(tripid);
			featureBuilder.add(time);
			featureBuilder.add(seconds);
			feature = featureBuilder.buildFeature(null);
			collection.add(feature);
		}

		//create transaction
		Transaction transaction = new DefaultTransaction("create");
		String typeName = writeDataStore.getTypeNames()[0];
		SimpleFeatureSource featureSource = writeDataStore.getFeatureSource(typeName);

		if (featureSource instanceof SimpleFeatureStore) {
			SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
			featureStore.setTransaction(transaction);
			try {
				featureStore.addFeatures(collection);
				transaction.commit();
			} catch (Exception problem) {
				problem.printStackTrace();
				transaction.rollback();
			} finally {
				transaction.close();
			}
			System.exit(0); // success!
		} else {
			System.out.println(typeName + " does not support read/write access");
			System.exit(1);
		}
		
	}
	
	//获取某个时间片段的快照Shapefile
	public static void getLinkTrafficMapSnapshot(int mins, int hour, Date day) throws IOException, NoSuchAuthorityCodeException, FactoryException{
		String timeStamp = new SimpleDateFormat("yyyy-mm-dd").format(day)+ "-" + hour + mins;
		
		//获取linktraffic
		List <AggLinkTraffic> linkTrafficDataSet = DBAccess.getLinkTraffic(mins, mins, hour, hour, day, -1);
		
		//获取路网
		//HashMap <String, Geometry> roadSegmentGeometrySet = DBAccess.getRoadGeometrySet();
		
		//高等级路网
		HashMap <String, Geometry> roadSegmentGeometrySet = DBAccess.getRoadGeometrySet("E:\\Data\\Road\\Wuhan_2010.9\\WuhanMainRoad_3rd_PATHNAME_wuchang6_EPSG32650.shp");

		System.out.println(roadSegmentGeometrySet.size());
		
		//创建shape
		JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
	    chooser.setDialogTitle("Save a new shapefile for a snapshot of the traffic road network");
	    
	    chooser.setSaveFile(new File("C:\\LinkTrafficMapSnapshot" + timeStamp + ".shp"));
	    
        if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) {
            return;
        }
        
        File outputShapefile = chooser.getSelectedFile();
		
		ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		Map<String, Serializable> params = null;
		ShapefileDataStore writeDataStore = null;
		SimpleFeatureType TYPE = null;
		
		try {
			params = new HashMap<String, Serializable>();
			params.put("url", outputShapefile.toURI().toURL());
			params.put("create spatial index", Boolean.TRUE);
			
			writeDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
			TYPE = DataUtilities.createType(
					"SampleRoadSegment",
					"GEOM:MultiLineString:srid=32650," 
					+ "ID:String," 
				    + "AVG:float," 
					+ "CARNUM:int,"
				    + "GPSNUM:int," 
                    + "STATUS:int," 
				    + "Time:String");
			
			writeDataStore.createSchema(TYPE);
			writeDataStore.forceSchemaCRS(CRS.decode("EPSG:32650", true));
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (SchemaException e) {
			e.printStackTrace();
		} 
		
		//prepare new feature collection	
		SimpleFeatureCollection collection = FeatureCollections.newCollection();
		SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
		SimpleFeature feature = null;
		MultiLineString line = null;
		Geometry geom = null;
		
        for (AggLinkTraffic linkTraffic : linkTrafficDataSet) {
        	geom =  roadSegmentGeometrySet.get(linkTraffic.linkID);
        	if(geom == null) 
        		continue;
        	line = (MultiLineString)geom;
			// create feature
			featureBuilder.add(line);
			featureBuilder.add(linkTraffic.linkID);
			featureBuilder.add(linkTraffic.avgSpeed);
			featureBuilder.add(linkTraffic.carNum);
			featureBuilder.add(linkTraffic.gpsNum);
			featureBuilder.add(linkTraffic.status);
			featureBuilder.add(timeStamp);
			feature = featureBuilder.buildFeature(null);
			collection.add(feature);
		}	

		//create transaction
		Transaction transaction = new DefaultTransaction("create");
		String typeName = writeDataStore.getTypeNames()[0];
		SimpleFeatureSource featureSource = writeDataStore.getFeatureSource(typeName);
		
		//create shape file
		if (featureSource instanceof SimpleFeatureStore) {
			SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
			featureStore.setTransaction(transaction);
			try {
				featureStore.addFeatures(collection);
				transaction.commit();
			} catch (Exception problem) {
				problem.printStackTrace();
				transaction.rollback();
			} finally {
				transaction.close();
			}
			System.exit(0); // success!
		} else {
			System.out.println(typeName + " does not support read/write access");
			System.exit(1);
		}
	}
	
	//去除路网的边界点
	public static void getRoadMapWithoutBorderPoints(String shapeRoadNetworkURL) throws IOException{
		// construct road network
		Network road = new Network(shapeRoadNetworkURL, false);
		
		ArrayList<String> idList =  new ArrayList <String>() ;
		
		for(Node node : road.nodeCollection.values()){
			if(node.getDegree() == 1)
				for(String edgeID : node.getAdjEdges()){
					idList.add(edgeID);
				}
		}
		
		// read shape file and get feature colletion
		FileDataStore readDataStore = FileDataStoreFinder.getDataStore(new File(shapeRoadNetworkURL));
		
		SimpleFeatureSource featureSource = readDataStore.getFeatureSource();
		
		//filter the border edge
	    FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(null);
	       
	    List<Filter> match = new ArrayList<Filter>();
	    
	    for( String id : idList){
	          Filter aMatch = ff.equals( ff.property( "ID"), ff.literal(id) );
	          match.add(aMatch);
	    }
	    
	    Filter filter = ff.or(match);
	    
	    SimpleFeatureCollection featureCollection = featureSource.getFeatures(ff.not(filter));
	    
	    //create a new shape file
		JFileDataStoreChooser chooser = new JFileDataStoreChooser("shp");
	    chooser.setDialogTitle("Save a new shapefile");
	    
	    chooser.setSaveFile(new File(shapeRoadNetworkURL));
	    
        if (chooser.showSaveDialog(null) != JFileChooser.APPROVE_OPTION) {
            return;
        }
        
        File outputShapefile = chooser.getSelectedFile();
	    
	    ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		Map<String, Serializable> params = null;
		ShapefileDataStore writeDataStore = null;
		
		try {
			params = new HashMap<String, Serializable>();
			params.put("url", outputShapefile.toURI().toURL());
			params.put("create spatial index", Boolean.TRUE);
			
			writeDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);		
			writeDataStore.createSchema(featureSource.getSchema());
			writeDataStore.forceSchemaCRS(DefaultGeographicCRS.WGS84);
			
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} 
		
		//create transaction
		Transaction transaction = new DefaultTransaction("create");
		String typeName = writeDataStore.getTypeNames()[0];
		featureSource = writeDataStore.getFeatureSource(typeName);
		
		//create shape file
		if (featureSource instanceof SimpleFeatureStore) {
			SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
			featureStore.setTransaction(transaction);
			try {
				featureStore.addFeatures(featureCollection);
				transaction.commit();
			} catch (Exception problem) {
				problem.printStackTrace();
				transaction.rollback();
			} finally {
				transaction.close();
			}
			System.exit(0); // success!
		} else {
			System.out.println(typeName + " does not support read/write access");
			System.exit(1);
		}
		
	}

	/*	
	//读取每辆车的数据，获取TrajectoryPoint与Trajectory对象，通过Trip计算LinkTraffic，并填充traffic_basic表
	public static void traj2linkTraffic(File csvFile, Network road) throws ShapefileException, IOException, MismatchedDimensionException, TransformException{
		Trajectory traj = DBAccess.getTrajectoryByCSVFile(csvFile);
		ArrayList<BasicLinkTraffic> linkTrafficList = new ArrayList<BasicLinkTraffic>();
		for(Trip trip : traj.getTrip()){
			ArrayList<BasicLinkTraffic> linkTraffics = getBasicLinkTraffic(trip,road);
			linkTrafficList.addAll(linkTraffics);
		}
		DBUpdate.populateBasicTrafficTable(linkTrafficList, "traffic_basic");
	}
 */
	
/*
	//通过Trip来获取LinkTraffic
	public static ArrayList <BasicLinkTraffic> getBasicLinkTraffic(Trip trip, Network road){
		ArrayList <BasicLinkTraffic> linkTrafficList = new ArrayList <BasicLinkTraffic> ();
		
		TrajectoryPoint prePoint = null;
		TrajectoryPoint nextPoint = null;
		
		String preCommonNodeID = null;
		int preEnterTime = 0;
		
		for(int i = 0; i < trip.points.size()- 1; i++) {
			prePoint = trip.points.get(i);
			nextPoint = trip.points.get(i+1);			
			if(prePoint.linkID.equals(nextPoint.linkID)) //位于同一路段
				continue;	
			String curCommonNodeID  = road.getCommonPoint(prePoint.linkID, nextPoint.linkID);
			if(curCommonNodeID != null) {//如果位于邻接路段，计算进入或离开的时间
				Edge preEdge = road.getEdgeById(prePoint.linkID);
				Edge curEdge = road.getEdgeById(nextPoint.linkID);
				double preDistance =  preEdge.getLinearDistance(curCommonNodeID, prePoint.geom.getCoordinate());
				double curDistance = curEdge.getLinearDistance(curCommonNodeID, nextPoint.geom.getCoordinate());				
				int preTime = prePoint.seconds;
				int curTime = nextPoint.seconds;				
				int curEnterTime = (int) ((preTime*curDistance + curTime*preDistance)/(preDistance + curDistance));
				if(preEdge.getAnotherNodeId(curCommonNodeID).equals(preCommonNodeID)) {//生成BasicLinkTraffic
					int travelTime = Math.abs(curEnterTime - preEnterTime);
					float travelSpeed = (float) ((preEdge.length/travelTime) * 3.6);
					BasicLinkTraffic linkTraffic = new BasicLinkTraffic(trip.carID, preEdge.id, preEnterTime, travelTime, travelSpeed);
				    System.out.println(
					"car: " + linkTraffic.carID + ", " 
					+ "tripID: " + trip.tripID  + ", " 
					+ "linkID: " + linkTraffic.linkID + ", " 
					+ "enterTime: " + linkTraffic.getTimeString() + ", " 
					+ "travleTime : " + travelTime + ", " 
					+ "speed: "+ travelSpeed);
					linkTrafficList.add(linkTraffic);
				}
				preCommonNodeID = curCommonNodeID;
				preEnterTime = curEnterTime;
			}
		}
		
		return linkTrafficList;
	}
*/
		
	//跨路段统计
	public static void pointPairingStatistic(String csvfileURL, Network road) throws ShapefileException, MismatchedDimensionException, IOException, TransformException  {
		Trajectory traj = DBAccess.getTrajectoryByCSVFile(new File(csvfileURL));
		
		TrajectoryPoint prePoint = null;
		TrajectoryPoint nextPoint = null;
		
        int sameRoadCount = 0;
		int adjacentRoadCount = 0;
		int crossRoadCount = 0;
		
		for(int i = 0; i < traj.points.size()- 1; i++) {
			prePoint = traj.points.get(i);
			nextPoint = traj.points.get(i+1);			
			if(prePoint.linkID.equals(nextPoint.linkID)) //位于同一路段
				sameRoadCount++;
			else if(road.getCommonPoint(prePoint.linkID, nextPoint.linkID)!= null){
				adjacentRoadCount++;
			}
			else
				crossRoadCount++;
		}
		
		System.out.println("Total num of Point Pair: " + Integer.toString(traj.points.size()- 1));
		System.out.println("Num of Same Road Point Pair: " + Integer.toString(sameRoadCount));
		System.out.println("Num of Adjacent Point Pair:" + Integer.toString(adjacentRoadCount));
		System.out.println("Num of Cross Point Pair:" + Integer.toString(crossRoadCount));
		
	}
	
	//坐标转换
	private static MathTransform getTransformFromEpsgCode(CoordinateReferenceSystem sourceCRS, String epsgCode) {
		CoordinateReferenceSystem targetCRS = null;
		MathTransform mathTransform = null;
		try {
			targetCRS = CRS.decode(epsgCode, true); 
			boolean lenient = true;
			mathTransform =CRS.findMathTransform(sourceCRS, targetCRS, lenient);
		} catch (NoSuchAuthorityCodeException e) {
			e.printStackTrace();
		} catch (FactoryException e) {
			e.printStackTrace();
		} 
		return mathTransform;
	}

	/** 
	 * Generate a new edge shapefile 
	 * 
	 * multilinkid = roadid + flag
	 * 
	 * flag: 
	 * 
	 * 01 双向
	 * 02 正向 ：自西向东；自南向北
	 * 03 逆向： 自东向西；自北向南
	 * 
	 * @throws IOException 
	 * @throws ShapefileException 
	 * @throws SchemaException 
	 * @throws FactoryException 
	 * @throws NoSuchAuthorityCodeException 
	 * 
	 * */

	//首先针对实验路段，然后进行扩展
	public static void getRoadEdgeWithMultiLinkReference(String shapeRoadNetworkURL) throws ShapefileException, IOException, SchemaException, NoSuchAuthorityCodeException, FactoryException{
		String positiveMultilinkid = "31602";
		String negativeMultilinkid = "31603";
		Edge negativeEdge = road.getEdgeById("45546302570"); // startEdge for multilink: 316 + 03 
		Edge positiveEdge = road.getEdgeById("45546201250"); // startEdge for multilink: 316 + 02   
        adjustRoadDigitalDirection(negativeEdge, negativeMultilinkid, 0);
        adjustRoadDigitalDirection(positiveEdge, positiveMultilinkid, 0);
        generateEdgeShapefile(road.edgeCollection.values().toArray(new Edge[]{}), shapeRoadNetworkURL);
	}
	
	//生成道路的Shapefile
	private static void generateEdgeShapefile(Edge[] edges, String edgeShapefileURL) throws IOException, SchemaException, NoSuchAuthorityCodeException, FactoryException {		
		ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
		Map<String, Serializable> params = new HashMap<String, Serializable>();
		params.put("url", new File(edgeShapefileURL).toURI().toURL());
		params.put("create spatial index", Boolean.TRUE);
		ShapefileDataStore writeDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);

		// specify the feature type
		final SimpleFeatureType TYPE = DataUtilities.createType(
				"RoadSegment",
				"GEOM:MultiLineString:srid=32650," 
				+ "ID:String," 
			    + "SNODEID:String," 
				+ "ENODEID:String,"
			    + "DIRECTION:String,"
				+ "LENGTH:float,"
                + "PATHNO:String," 
			    + "MLINKID:String,"
			    + "SOFFSET:float,"
			    + "EOFFSET:float"); //+ "DIRECTION:int,"

		writeDataStore.createSchema(TYPE);
		writeDataStore.forceSchemaCRS(CRS.decode("EPSG:32650", true));

		//prepare new feature collection	
		SimpleFeatureCollection collection = FeatureCollections.newCollection();
		SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);

		SimpleFeature feature = null;
		
		for (Edge edge : edges) {
			// create feature	
			featureBuilder.add(new GeometryFactory().createMultiLineString(new LineString[]{edge.line}));
			featureBuilder.add(edge.id);
			featureBuilder.add(edge.startNodeID);
			featureBuilder.add(edge.endNodeID);
			featureBuilder.add(null);
			featureBuilder.add(edge.length);
			featureBuilder.add(edge.pathno);
			featureBuilder.add(edge.multiLinkID1);
			featureBuilder.add(edge.startOffset1);
			featureBuilder.add(edge.endOffset1);
			feature = featureBuilder.buildFeature(null);
			collection.add(feature);
		}

		//create transaction
		Transaction transaction = new DefaultTransaction("create");
		String typeName = writeDataStore.getTypeNames()[0];
		SimpleFeatureSource featureSource = writeDataStore.getFeatureSource(typeName);

		if (featureSource instanceof SimpleFeatureStore) {
			SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
			featureStore.setTransaction(transaction);
			try {
				featureStore.addFeatures(collection);
				transaction.commit();
			} catch (Exception problem) {
				problem.printStackTrace();
				transaction.rollback();
			} finally {
				transaction.close();
			}
			System.exit(0); // success!
		} else {
			System.out.println(typeName + " does not support read/write access");
			System.exit(1);
		}	
	}
	
	//调整数字化方向，使其与道路方向一致;同时建立线性参考
	private static void adjustRoadDigitalDirection(Edge edge, String multilinkid, float offset){
		edge.multiLinkID1 = multilinkid;
		edge.startOffset1 = offset;
		edge.endOffset1 = (float) (offset + edge.length);
		if(edge.direction == 3){
			String tempNodeID = edge.startNodeID;
			edge.startNodeID = edge.endNodeID;
			edge.endNodeID = tempNodeID;
			edge.line.reverse();
		}
		Node adjNode = road.getNodeById(edge.endNodeID);
		if(adjNode.numOfEdge ==1 ) 
			return;
		String adjEdgeID = adjNode.getAdjEdges(edge.id)[0];
		adjustRoadDigitalDirection(road.getEdgeById(adjEdgeID), multilinkid, edge.endOffset1);
	}
	
	public static void generateTrafficStatusMatrixByMLink(String mLinkID, int startHour, int endHour, Date day) throws IOException {
		
		ArrayList <String> edgeIDList = road.multiLinkCollection.get(mLinkID).edgeIDList;
		
		int row = edgeIDList.size();
	
		int column = (endHour - startHour + 1) * 12;
		
		int[][] statusMatrix = new int[row][column]; //统一初始化为0
				
		List<AggLinkTraffic> linkTrafficDataSet = null;
		
		//矩阵填充
		for(int i = 0; i < row; i++){
			linkTrafficDataSet = DBAccess.getLinkTrafficByLink(edgeIDList.get(i), startHour, endHour, day, -1);			
			if(linkTrafficDataSet.size() == 0)
				continue;
			for(AggLinkTraffic linkTraffic : linkTrafficDataSet){
				int index = linkTraffic.hour * 12 + linkTraffic.timeInterval - startHour*12;
				statusMatrix[i][index -1] = linkTraffic.status + 2;
			}
		}
		
		PrintWriter writer = new PrintWriter(new FileWriter("D:\\MLinkTraffic.txt", true));
		
		for(int i = 0; i < row; i++){
			writer.print(edgeIDList.get(i) + ", ");
			for(int j = 0; j < column - 1; j++ ){
				writer.print(statusMatrix[i][j] + ",  ");
			}
			writer.println(statusMatrix[i][column - 1]);
		}
		
		writer.close();
	}
	
	public static void generateTrafficStatusMatrixByLink(String linkID, int startHour, int endHour, Date day) throws IOException {
			
		int column = (endHour - startHour + 1) * 12;
		
		int[] statusMatrix = new int[column]; //统一初始化为0
				
		List<AggLinkTraffic> linkTrafficDataSet = null;
		
		//矩阵填充
		linkTrafficDataSet = DBAccess.getLinkTrafficByLink(linkID, startHour, endHour, day, -1);
		
		if(linkTrafficDataSet.size() == 0)
			return;
		
		for(AggLinkTraffic linkTraffic : linkTrafficDataSet){			
			int index = linkTraffic.hour * 12 + linkTraffic.timeInterval - startHour*12;
			statusMatrix[index -1] = linkTraffic.status + 2;
		}
				
		PrintWriter writer = new PrintWriter(new FileWriter("D:\\LinkTraffic.txt", true));

		for(int j = 0; j < column - 1; j++ ){
			writer.print(statusMatrix[j] + ",  ");
		}
		
		writer.println(statusMatrix[column - 1]);

		writer.close();
	}
	
	public static void main(String[] args) {
		try {
			//TrafficDataAnalysis.outputSampleRoadSegment("D:\\CSVSample\\200812280815_Sample.csv", "D:\\Road\\RWuhan45_polyline");
			//TrafficDataAnalysis.outputSampleRoadSegmentCentroid("D:\\ShapeSample\\SampleSegment_0800_0805.shp");
			//TrafficDataAnalysis.shape2arff("D:\\Sample\\SamplePoints_0800_0805.shp", "D:\\Lin Xu\\Desktop\\SamplePoints_0800_0805.arff");
			
		    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-mm-dd");
			
		    TrafficDataAnalysis.init("E:\\Data\\论文实验\\Road\\WuhanMainRoad_3rd_PATHNAME_wuchang6_EPSG32650.shp", "E:\\Data\\论文实验\\Road\\road.txt");
					
            TrafficDataAnalysis.generateTrafficStatusMatrixByMLink("31611", 7, 8, dateFormat.parse("2009-3-8")); // 珞瑜路（广埠屯--鲁巷方向）
            
            //TrafficDataAnalysis.generateTrafficStatusMatrixByLink("45546207970", 0, 23, dateFormat.parse("2009-3-9"));
										
			//TrafficDataAnalysis.getLinkTrafficMapSnapshot(6, 8, dateFormat.parse("2008-12-28"));
			
			//TrafficDataAnalysis.getRoadMapWithoutBorderPoints("D:\\WuhanCarRoad.shp");
			//TrafficDataAnalysis.getRoadSegmentsEndPonit("D://VIPRoadBySQL");
            /*			
             * File[] files = new File("D:\\Lin Xu\\My Documents\\GISDataBase\\FCD\\Taxi_Li\\20081228").listFiles();
			   for(File file : files){csv2LinkTraffic(file);}
			*/
			//pointPairingStatistic("D:\\Lin Xu\\My Documents\\GISDataBase\\FCD\\Taxi_Li\\20081228\\11201.txt", new Network("D:\\Data\\Road\\Wuhan_2010.9\\RWuhan45_polyline_EPSG32650.shp"));
			//csv2shape("D:\\Lin Xu\\My Documents\\GISDataBase\\FCD\\Taxi_Li\\20081228\\11201.txt");
/*			init("D:\\LuoyuRoad.shp");
			getRoadEdgeWithMultiLinkReference("D:\\NewLuoyuRoad.shp");*/
			
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}
